/**
 * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package de.hsmannheim.pepa.patientenportal.apanwep.service;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ClassLoaderObjectInputStream;
import com.liferay.portal.kernel.util.PropsUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.BaseModel;

import de.hsmannheim.pepa.patientenportal.apanwep.model.chronikClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.contactClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.messageClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.message_objectsClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.message_participantsClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.messages_mobjectsClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.messages_mparticipantsClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.objectsClp;
import de.hsmannheim.pepa.patientenportal.apanwep.model.participantsClp;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Cedric Nana
 */
public class ClpSerializer {
	public static String getServletContextName() {
		if (Validator.isNotNull(_servletContextName)) {
			return _servletContextName;
		}

		synchronized (ClpSerializer.class) {
			if (Validator.isNotNull(_servletContextName)) {
				return _servletContextName;
			}

			try {
				ClassLoader classLoader = ClpSerializer.class.getClassLoader();

				Class<?> portletPropsClass = classLoader.loadClass(
						"com.liferay.util.portlet.PortletProps");

				Method getMethod = portletPropsClass.getMethod("get",
						new Class<?>[] { String.class });

				String portletPropsServletContextName = (String)getMethod.invoke(null,
						"apanwep-portlet-deployment-context");

				if (Validator.isNotNull(portletPropsServletContextName)) {
					_servletContextName = portletPropsServletContextName;
				}
			}
			catch (Throwable t) {
				if (_log.isInfoEnabled()) {
					_log.info(
						"Unable to locate deployment context from portlet properties");
				}
			}

			if (Validator.isNull(_servletContextName)) {
				try {
					String propsUtilServletContextName = PropsUtil.get(
							"apanwep-portlet-deployment-context");

					if (Validator.isNotNull(propsUtilServletContextName)) {
						_servletContextName = propsUtilServletContextName;
					}
				}
				catch (Throwable t) {
					if (_log.isInfoEnabled()) {
						_log.info(
							"Unable to locate deployment context from portal properties");
					}
				}
			}

			if (Validator.isNull(_servletContextName)) {
				_servletContextName = "apanwep-portlet";
			}

			return _servletContextName;
		}
	}

	public static Object translateInput(BaseModel<?> oldModel) {
		Class<?> oldModelClass = oldModel.getClass();

		String oldModelClassName = oldModelClass.getName();

		if (oldModelClassName.equals(chronikClp.class.getName())) {
			return translateInputchronik(oldModel);
		}

		if (oldModelClassName.equals(contactClp.class.getName())) {
			return translateInputcontact(oldModel);
		}

		if (oldModelClassName.equals(messageClp.class.getName())) {
			return translateInputmessage(oldModel);
		}

		if (oldModelClassName.equals(message_objectsClp.class.getName())) {
			return translateInputmessage_objects(oldModel);
		}

		if (oldModelClassName.equals(message_participantsClp.class.getName())) {
			return translateInputmessage_participants(oldModel);
		}

		if (oldModelClassName.equals(messages_mobjectsClp.class.getName())) {
			return translateInputmessages_mobjects(oldModel);
		}

		if (oldModelClassName.equals(messages_mparticipantsClp.class.getName())) {
			return translateInputmessages_mparticipants(oldModel);
		}

		if (oldModelClassName.equals(objectsClp.class.getName())) {
			return translateInputobjects(oldModel);
		}

		if (oldModelClassName.equals(participantsClp.class.getName())) {
			return translateInputparticipants(oldModel);
		}

		return oldModel;
	}

	public static Object translateInput(List<Object> oldList) {
		List<Object> newList = new ArrayList<Object>(oldList.size());

		for (int i = 0; i < oldList.size(); i++) {
			Object curObj = oldList.get(i);

			newList.add(translateInput(curObj));
		}

		return newList;
	}

	public static Object translateInputchronik(BaseModel<?> oldModel) {
		chronikClp oldClpModel = (chronikClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getchronikRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputcontact(BaseModel<?> oldModel) {
		contactClp oldClpModel = (contactClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getcontactRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputmessage(BaseModel<?> oldModel) {
		messageClp oldClpModel = (messageClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getmessageRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputmessage_objects(BaseModel<?> oldModel) {
		message_objectsClp oldClpModel = (message_objectsClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getmessage_objectsRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputmessage_participants(
		BaseModel<?> oldModel) {
		message_participantsClp oldClpModel = (message_participantsClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getmessage_participantsRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputmessages_mobjects(BaseModel<?> oldModel) {
		messages_mobjectsClp oldClpModel = (messages_mobjectsClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getmessages_mobjectsRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputmessages_mparticipants(
		BaseModel<?> oldModel) {
		messages_mparticipantsClp oldClpModel = (messages_mparticipantsClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getmessages_mparticipantsRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputobjects(BaseModel<?> oldModel) {
		objectsClp oldClpModel = (objectsClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getobjectsRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInputparticipants(BaseModel<?> oldModel) {
		participantsClp oldClpModel = (participantsClp)oldModel;

		BaseModel<?> newModel = oldClpModel.getparticipantsRemoteModel();

		newModel.setModelAttributes(oldClpModel.getModelAttributes());

		return newModel;
	}

	public static Object translateInput(Object obj) {
		if (obj instanceof BaseModel<?>) {
			return translateInput((BaseModel<?>)obj);
		}
		else if (obj instanceof List<?>) {
			return translateInput((List<Object>)obj);
		}
		else {
			return obj;
		}
	}

	public static Object translateOutput(BaseModel<?> oldModel) {
		Class<?> oldModelClass = oldModel.getClass();

		String oldModelClassName = oldModelClass.getName();

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.chronikImpl")) {
			return translateOutputchronik(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.contactImpl")) {
			return translateOutputcontact(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.messageImpl")) {
			return translateOutputmessage(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.message_objectsImpl")) {
			return translateOutputmessage_objects(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.message_participantsImpl")) {
			return translateOutputmessage_participants(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.messages_mobjectsImpl")) {
			return translateOutputmessages_mobjects(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.messages_mparticipantsImpl")) {
			return translateOutputmessages_mparticipants(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.objectsImpl")) {
			return translateOutputobjects(oldModel);
		}

		if (oldModelClassName.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.model.impl.participantsImpl")) {
			return translateOutputparticipants(oldModel);
		}

		return oldModel;
	}

	public static Object translateOutput(List<Object> oldList) {
		List<Object> newList = new ArrayList<Object>(oldList.size());

		for (int i = 0; i < oldList.size(); i++) {
			Object curObj = oldList.get(i);

			newList.add(translateOutput(curObj));
		}

		return newList;
	}

	public static Object translateOutput(Object obj) {
		if (obj instanceof BaseModel<?>) {
			return translateOutput((BaseModel<?>)obj);
		}
		else if (obj instanceof List<?>) {
			return translateOutput((List<Object>)obj);
		}
		else {
			return obj;
		}
	}

	public static Throwable translateThrowable(Throwable throwable) {
		if (_useReflectionToTranslateThrowable) {
			try {
				UnsyncByteArrayOutputStream unsyncByteArrayOutputStream = new UnsyncByteArrayOutputStream();
				ObjectOutputStream objectOutputStream = new ObjectOutputStream(unsyncByteArrayOutputStream);

				objectOutputStream.writeObject(throwable);

				objectOutputStream.flush();
				objectOutputStream.close();

				UnsyncByteArrayInputStream unsyncByteArrayInputStream = new UnsyncByteArrayInputStream(unsyncByteArrayOutputStream.unsafeGetByteArray(),
						0, unsyncByteArrayOutputStream.size());

				Thread currentThread = Thread.currentThread();

				ClassLoader contextClassLoader = currentThread.getContextClassLoader();

				ObjectInputStream objectInputStream = new ClassLoaderObjectInputStream(unsyncByteArrayInputStream,
						contextClassLoader);

				throwable = (Throwable)objectInputStream.readObject();

				objectInputStream.close();

				return throwable;
			}
			catch (SecurityException se) {
				if (_log.isInfoEnabled()) {
					_log.info("Do not use reflection to translate throwable");
				}

				_useReflectionToTranslateThrowable = false;
			}
			catch (Throwable throwable2) {
				_log.error(throwable2, throwable2);

				return throwable2;
			}
		}

		Class<?> clazz = throwable.getClass();

		String className = clazz.getName();

		if (className.equals(PortalException.class.getName())) {
			return new PortalException();
		}

		if (className.equals(SystemException.class.getName())) {
			return new SystemException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchchronikException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchchronikException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchcontactException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchcontactException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessageException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessageException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessage_objectsException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessage_objectsException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessage_participantsException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessage_participantsException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessages_mobjectsException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessages_mobjectsException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessages_mparticipantsException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchmessages_mparticipantsException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchobjectsException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchobjectsException();
		}

		if (className.equals(
					"de.hsmannheim.pepa.patientenportal.apanwep.NoSuchparticipantsException")) {
			return new de.hsmannheim.pepa.patientenportal.apanwep.NoSuchparticipantsException();
		}

		return throwable;
	}

	public static Object translateOutputchronik(BaseModel<?> oldModel) {
		chronikClp newModel = new chronikClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setchronikRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputcontact(BaseModel<?> oldModel) {
		contactClp newModel = new contactClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setcontactRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputmessage(BaseModel<?> oldModel) {
		messageClp newModel = new messageClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setmessageRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputmessage_objects(BaseModel<?> oldModel) {
		message_objectsClp newModel = new message_objectsClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setmessage_objectsRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputmessage_participants(
		BaseModel<?> oldModel) {
		message_participantsClp newModel = new message_participantsClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setmessage_participantsRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputmessages_mobjects(BaseModel<?> oldModel) {
		messages_mobjectsClp newModel = new messages_mobjectsClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setmessages_mobjectsRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputmessages_mparticipants(
		BaseModel<?> oldModel) {
		messages_mparticipantsClp newModel = new messages_mparticipantsClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setmessages_mparticipantsRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputobjects(BaseModel<?> oldModel) {
		objectsClp newModel = new objectsClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setobjectsRemoteModel(oldModel);

		return newModel;
	}

	public static Object translateOutputparticipants(BaseModel<?> oldModel) {
		participantsClp newModel = new participantsClp();

		newModel.setModelAttributes(oldModel.getModelAttributes());

		newModel.setparticipantsRemoteModel(oldModel);

		return newModel;
	}

	private static Log _log = LogFactoryUtil.getLog(ClpSerializer.class);
	private static String _servletContextName;
	private static boolean _useReflectionToTranslateThrowable = true;
}